use crate::context::CONTEXT;
use crate::modules::system::domain::dto::profile::PasswordUpdateDTO;
use crate::system::domain::dto::ProfileUpdateDTO;
use crate::system::domain::mapper::sys_user::SysUser;
use crate::system::domain::vo::{CommonDeptVO, CommonUserVO};
use crate::utils::password_encoder::PasswordEncoder;
use crate::{error_wrapper, error_wrapper_unwrap, update_marco, RespJson, RespVO};
use axum::extract::Query;
use axum::response::IntoResponse;
use axum::Json;
use macros::pre_authorize;
use std::time::Duration;
/*
* 用户自身的操作
*/

//的用户信息
#[pre_authorize(user_cache)]
pub async fn profile() -> impl IntoResponse {
    let mut res = RespJson::success_info("操作成功");
    error_wrapper_unwrap!(CONTEXT.sys_user_service.detail(&user_cache.user_id), user);
    let mut user = CommonUserVO::from(user);
    user.dept=Some(CommonDeptVO{
        dept_id: user_cache.dept_id.into(),
        dept_name:  user_cache.dept_name.into(),
    });
    res.insert("data".to_string(), serde_json::json!(user));
    res.insert(
        "postGroup".to_string(),
        serde_json::json!(CONTEXT
            .sys_post_service
            .select_post_names_by_user_name(&&user_cache.user_name)
            .await
            .unwrap_or_default()
            .join(",")),
    );
    res.insert(
        "roleGroup".to_string(),
        serde_json::json!(user_cache
            .roles
            .clone()
            .into_iter()
            .map(|r| r.role_name.unwrap())
            .collect::<Vec<_>>()
            .join(",")),
    );
    res.into_response()
}

//todo 重新设计 用户自行修改用户信息
#[pre_authorize(user_cache)]
pub async fn update_profile(dto: Json<ProfileUpdateDTO>) -> impl IntoResponse {
    update_marco!(data, dto, user_cache, SysUser);
    data.user_id = user_cache.user_id.clone().into();

    error_wrapper!(CONTEXT.sys_user_service.update_profile(data.clone()), res);

    let res = CONTEXT
        .cache_service
        .set_string_ex(
            &user_cache.token_key,
            &user_cache.to_string(),
            Some(Duration::from_secs(CONTEXT.config.token_expired_min * 60)),
        )
        .await;

    RespVO::from_result(&res).into_response()
}

//用户自行修改密码
#[pre_authorize(user_cache)]
pub async fn update_pwd(dto: Query<PasswordUpdateDTO>) -> impl IntoResponse {

    let user_id = user_cache.user_id.clone();
    error_wrapper_unwrap!(CONTEXT.sys_user_service.find_by_user_id(&user_id), user);
    let new_password = &dto.new_password;
    let old_password = &dto.old_password;
    if new_password.eq(old_password) {
        return RespVO::<u64>::from_error_info(500, "新密码不能与旧密码相同").into_response();
    }

    if !PasswordEncoder::verify(
        &user.password.unwrap_or_default(),
        &old_password.clone().unwrap_or_default(),
    ) {
        return RespVO::<u64>::from_error_info(500, "修改密码失败，旧密码错误").into_response();
    }
    let res = CONTEXT
        .sys_user_service
        .update_password_raw(
            &PasswordEncoder::encode(&new_password.clone().unwrap_or_default()),
            &user_id,
        )
        .await;
    RespVO::<u64>::judge_result(res, "修改密码成功！", "修改密码失败！").into_response()
}
